#include "stdogre.h"
#include "OgreMain.h"
#include "SAFrameListener.h"
#include <cmath>
#include "ControlPointManager.h"

int OgreMain::Setup( Ogre::String ResourcePath, Ogre::String PluginPath )
{
	m_ResourcePath = ResourcePath;
	m_PluginPath = PluginPath;
	m_Root = OGRE_NEW Ogre::Root(PluginPath, 
		ResourcePath + "ogre.cfg", ResourcePath + "Ogre.log");
	return STETUP_OK;
}

int OgreMain::Initalize(int w, int h)
{
	Ogre::RenderSystem* mRSys = m_Root->getRenderSystemByName("Direct3D9 Rendering Subsystem");
	if(mRSys == NULL)
	{
		::MessageBox(NULL,L"cannot find Direct3D9 Rendering Subsystem",L"error",MB_OK);
		::exit(0);
	}
	m_Root->setRenderSystem(mRSys);
	// create render window
	m_hwnd = m_Win32Window.ToCreateWindow(100, 100, w, h, L"OgreTrackTrain");
	m_Win32Window.ToShow();
	Ogre::NameValuePairList opts;
	opts["externalWindowHandle"] = Ogre::StringConverter::toString((unsigned long)m_hwnd);
	m_RenderWindow = m_Root->initialise(false);
	m_RenderWindow = m_Root->createRenderWindow("School Adventure", w, h, false, &opts);
	
	m_UpdateTime = 1.0/85;
	ChooseSceneManager();
	CreateCamera();
	SetupResources();
	Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(3);
	Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
	CreateViewports();
	CreateScene();
	ShowLoading();
	m_Root->renderOneFrame();
	CreateFrameListener();
	
	return INITALIZE_OK;
}

void OgreMain::Go()
{
	Timer OneSecondTimer;
	int fps=0;
	double time;
	OneSecondTimer.Restart();
	m_FrameTimer.Restart();
	for (;!m_FrameListener->IsShutDown();)
	{
		if (m_FrameTimer.GetTime() >= m_UpdateTime)
		{
			fps++;
			m_Root->renderOneFrame();
			UpdateFrame();
			m_Win32Window.HandlePeekMessage();
			m_FrameTimer.ReTick();
		}
		else
			Sleep(1);
		if (time = OneSecondTimer.GetTime() > 0.2)
		{
			if (fps/time > 63/5.0)
				m_UpdateTime += 0.0003;
			else if (fps/time < 60/5.0)
				m_UpdateTime -= 0.0003;
			fps = 0;
			OneSecondTimer.ReTick();
		}
	}
}

int OgreMain::SetBGM( Ogre::String soundpath )
{
	return SETBGM_OK;
}

void OgreMain::ChooseSceneManager()
{
	m_SceneMgr = m_Root->createSceneManager(Ogre::ST_EXTERIOR_CLOSE);
}

void OgreMain::CreateCamera()
{
	using namespace Ogre;
	// Create the camera
	m_Camera = m_SceneMgr->createCamera("cam");
	// Position it at 500 in Z direction
	m_Camera->setPosition(Ogre::Vector3(0,0,0));
	// Look back along -Z
	m_Camera->lookAt(Ogre::Vector3(1000, 10, 1000));
	m_Camera->setNearClipDistance(50);
	m_CamNode = m_SceneMgr->createSceneNode("PlayerCam");
	m_CamNode->attachObject(m_Camera);
	m_CamNode->setPosition(Ogre::Vector3(5000,500,5000));
}

void OgreMain::SetupResources()
{
	// Load resource paths from config file
	Ogre::ConfigFile cf;
#ifdef _DEBUG
	cf.load(m_ResourcePath + "resources_d.cfg");
#else
	cf.load(m_ResourcePath + "resources.cfg");
#endif
	
	// Go through all sections & settings in the file
	Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
	Ogre::String secName, typeName, archName;
	while (seci.hasMoreElements())
	{
		secName = seci.peekNextKey();
		Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
		Ogre::ConfigFile::SettingsMultiMap::iterator i;
		for (i = settings->begin(); i != settings->end(); ++i)
		{
			typeName = i->first;
			archName = i->second;
			Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
				archName, typeName, secName);
		}
	}
}

void OgreMain::CreateViewports()
{
	using namespace Ogre;
	// Create one viewport, entire window
	m_ViewPort = m_RenderWindow->addViewport(m_Camera);
	m_ViewPort->setBackgroundColour(ColourValue(0.2f, 0.2f, 0.0f));
	// Alter the camera aspect ratio to match the viewport
	m_Camera->setAspectRatio(Real(m_ViewPort->getActualWidth()) / Real(m_ViewPort->getActualHeight()));
}

void OgreMain::CreateScene()
{
	using namespace Ogre;
	// Set ambient light
	m_SceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_TEXTURE_ADDITIVE);
	m_SceneMgr->setSkyDome(true, "Examples/CloudySky", 10, 10);
	m_SceneMgr->setWorldGeometry("terrain.cfg");
	//m_Camera->setPosition(500,500, 1500);
	//m_Camera->lookAt(0,200,-300);
	m_SceneMgr->setAmbientLight(ColourValue(0.3f, 0.3f, 0.3f));
	// Create a point light
	Light* l = m_SceneMgr->createLight("MainLight");
	l->setType(Light::LT_DIRECTIONAL);
	l->setDirection(-0.5, -0.5, 0);
}

void OgreMain::ShowLoading()
{

}

void OgreMain::ReleaseResources()
{
	delete m_FrameListener;
	delete m_SceneMgr;
	delete m_RenderWindow;
}

void OgreMain::PlayBGM(std::wstring path)
{
	wchar_t buf[128];
	//use mciSendString()
	mciSendString((L"play "+ path).c_str(), buf, sizeof(buf),NULL);
	mciSendString((L"setaudio " + path + L" volume to 200").c_str(), buf,sizeof(buf),NULL);
}

void OgreMain::StopBGN(std::wstring path)
{
	wchar_t buf[128];
	mciSendString((L"stop " + path).c_str(), buf, sizeof(buf),NULL);
}

void OgreMain::CreateFrameListener()
{
	setupHikari();
	m_FrameListener = new SAFrameListener(m_SceneMgr, m_RenderWindow, m_Camera, m_hikariMgr);
	m_Root->addFrameListener(m_FrameListener);	
}

void OgreMain::UpdateFrame()
{
	m_hikariMgr->update();
}

void OgreMain::setupHikari()
{
	using Hikari::FlashDelegate;
	using Hikari::Position;
	m_hikariMgr = shared_ptr<Hikari::HikariManager>(new Hikari::HikariManager("media"));
	
	m_controls = m_hikariMgr->createFlashOverlay("Controls", m_ViewPort, 2000, 400, Position(0,0));
	m_controls->load("Interface.swf");
	m_controls->setTransparent(true, true);
	m_controls->bind("Exit", FlashDelegate(this, &OgreMain::FlCall_Exit));
	
}

Hikari::FlashValue OgreMain::FlCall_Exit( Hikari::FlashControl* caller, const Hikari::Arguments& args )
{
	m_FrameListener->m_ShutDown = true;
	return FLASH_VOID;
}


